import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress' // 进度条
import 'nprogress/nprogress.css' // 进度条样式
import { getToken } from '@/utils/auth' // 从 cookie 中获取令牌
import getPageTitle from '@/utils/get-page-title'

import Router from 'vue-router'

// 登录拦截配置文件

NProgress.configure({ showSpinner: false }) // NProgress 配置

const whiteList = ['/login'] // 重定向白名单

// 全局前置路由守卫
router.beforeEach(
  // 表示异步执行
  async(to, from, next) =>
  {
    // 开始进度条
    NProgress.start()

    // 设置页面标题
    document.title = getPageTitle(to.meta.title)

    // 获取本地 Cookies 中，是否有 token
    const hasToken = getToken()

    // 是否获取到登录信息token
    if (hasToken) {
      // 判断要去的地方，是不是 登录 页面
      if (to.path === '/login') {
        // 如果是登录页面，则跳转到 主页
        next({ path: '/' })

        // 进度条加载完毕
        NProgress.done()

      } else {  // 这里表示要去的地方，不是登录页面

        // 如果用户要去的地方，不是登录页面，就去获取 由 store 托管的用户名
        const hasGetUserInfo = store.getters.name

        // 判断是否获取到了用户名
        if (hasGetUserInfo) {
          // 获取到了，就放行
          next()

        } else {
          try {
            // 如果没有用户名，则等待加载用户名完成，这里也是使用 动作 来根据 token 从服务器加载
            // await ： 和 async 一起使用，async 表示异步执行，await 表示等待执行结果
            // 并且这里返回的是 Promise 对象，可以使用 then 方法获取到返回的数据
            await store.dispatch('user/getInfo')

            // 获取到用户名之后，放行，没有获取到用户名，则抛出异常
            // 一般情况下，我们的 store 中的数据，是在运行阶段进行赋值的，除非扒源码，否则不太可能破解
            // 并且 token 也有过期时间，超过了就无效，且 token 很难被破解
            next()
          } catch (error) {
            // 如果上面的获取 用户信息 动作，抛出了异常，则删除本地的 token
            await store.dispatch('user/resetToken')
            // 等待删除完成之后，提示错误信息
            Message.error(error || 'Has Error')
            // 跳转到登录页面，但是传递了当前想去的页面信息，到 query 路由参数中
            next(`/login?redirect=${to.path}`)
            // 进度条加载完毕
            NProgress.done()
          }
        }
      }
    } else {
      // 进入到这里，就是用户浏览器中，没有 token
      if (whiteList.indexOf(to.path) !== -1) {
        // 这里是表示，在 whiteList 白名单集合里面 找到 to.path 的字符串值
        // 如果返回的结果为 -1 ，则表示白名单里面有，直接放行
        next()
      } else {
        // 进入到这里，则表示白名单里面没有，直接拦截即可，但是需要将当前要跳转的页面，进行记录
        next(`/login?redirect=${to.path}`)
        // 加载完毕，关闭加载页面
        NProgress.done()
      }
    }
  })
// 全局后置路由守卫，这里是为了防止白名单跳转之后，进度条未关闭
router.afterEach(() => {
  // 完成进度条
  NProgress.done()
  //----------------------------- 获取菜单栏 ----------------------
  // 创建组件时，进行获取菜单栏
  store.dispatch('permission/generateRoutes').then(res => {
      // 为了防止控制台出现警告
      router.options.routes = res
      router.matcher = new Router().matcher
      // 经过上面的设置，在添加不会出现警告
      router.addRoutes(router.options.routes)

  })

})
